package servidorIndice.controlador;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import javax.net.ssl.*;
import javax.net.ServerSocketFactory;


/**
 * Clase que se implementará el servidor indice
 * @author Jorge Hernán Londoño Echeverri narzyx@gmail.com Hayner Benavides Moreno hayner2005@gmail.com
 *
 */
public class ServidorIndice extends Thread {
    private ServerSocket serverSocket;
   // private ServerSocketFactory factory;
    private static int PORT;
    private ArrayList<String> bitacoraClientes;

    private java.util.ArrayList<ProcesarServidorIndice> listaProcesos;

    /**
     * Contructor de la clase
     */
    public ServidorIndice() {
     //   System.setProperty("javax.net.ssl.keyStore","ssl/miLlavero");
     //   System.setProperty("javax.net.ssl.keyStorePassword", "123456");
        serverSocket = null;
        PORT = 7777;
        bitacoraClientes = new ArrayList<String>();
        listaProcesos = new ArrayList<ProcesarServidorIndice>();
        this.limpiar();
        //factory = SSLServerSocketFactory.getDefault();
    }

    public void run(){
        try{
            if(isEnlazado()){
                int indice=1;
                while(true){
                   // System.out.println("esperando");
                    java.net.Socket cliente= esperar();
                    if(cliente!=null){
                        System.out.println("se ha iniciado el socket");
                        ProcesarServidorIndice procesador= new ProcesarServidorIndice(cliente,indice);
                        procesador.start();
                        listaProcesos.add(procesador);
                        indice++;
                    }
                }
            }
        }
        catch(Exception e){
            System.out.println("hay un problema "+e.getMessage());
        }
    }

    /**
     * Método que permite saber si el Socket se ha enlazado
     * por medio del pueroto que se ha definido por defecto
     * @return true si se ha enlazado, false en casoc ontrario
     */
    public boolean isEnlazado() {
        try {
            serverSocket = new ServerSocket(PORT);
           // System.out.println("se ha conectado al puerto "+PORT);
            //serverSocket = factory.createServerSocket(PORT);
        } catch (Exception e) {
            this.setServerSocket(null);
            
            return false;
        }
        return true;
    }

    /**
     * Método que permite implemnetar la espera
     * del socket que vaya a conectarse por el puerto establecido
     * @return Socket
     * @throws java.lang.Exception
     */
    public Socket esperar() throws Exception{
        Socket socket_llegada = null;
        try{
            socket_llegada = serverSocket.accept();
        }
        catch(IOException ioe){
         //   System.out.println("Se ha presentando un problema en el método de espera para realizar el accept()");
           // ioe.printStackTrace();
            throw new Exception("Se ha presentando un problema en el método de espera para realizar el accept(): ", ioe);
        }

        return socket_llegada;
    }
    /**
     * Método que permite eliminar un proceso
     * de la base de datos por medio del indice
     * @param indice
     */
    public void eliminarProceso(int indice){
        try{

            RegistrosControlador controlador = new RegistrosControlador();
            if( controlador.init("sqlite")){
                controlador.eliminarRegistro(indice);
                controlador.cerrar();
            }
            
            for(int i=0; i<this.listaProcesos.size();i++){
                if(this.listaProcesos.get(i).getIndice()==indice){
                    
                    this.listaProcesos.get(i).terminar();
                    obtenerBitacora();
                    this.listaProcesos.get(i).interrupt();
                    this.listaProcesos.remove(i);                    
                    break;
                }
            }
        }
        catch(Exception ex){
            System.out.println("Se ha presentado un error en eliminar proceso");
            //ex.printStackTrace();
        }
        
    }
    /**
     * Método que invoca al eliminar de todos los registros
     */
    public void limpiar(){
        RegistrosControlador controlador = new RegistrosControlador();
        if(controlador.init("sqlite")){
            controlador.eliminarRegistro();
        }
    }
    
    ////////////////////////////////////////////////////////////////////////////

    public static int getPORT() {
        return PORT;
    }

    public static void setPORT(int PORT) {
        ServidorIndice.PORT = PORT;
    }

    public ServerSocket getServerSocket() {
        return serverSocket;
    }

    public void setServerSocket(ServerSocket serverSocket) {
        this.serverSocket = serverSocket;
    }

   /* public ServerSocketFactory getFactory() {
        return factory;
    }

    public void setFactory(ServerSocketFactory factory) {
        this.factory = factory;
    }*/

    public ArrayList<ProcesarServidorIndice> getListaProcesos() {
        return listaProcesos;
    }

    public void setListaProcesos(ArrayList<ProcesarServidorIndice> listaProcesos) {
        this.listaProcesos = listaProcesos;
    }

    public ArrayList<String> getBitacoraClientes() {
        obtenerBitacora();
        return bitacoraClientes;
    }

    public void setBitacoraClientes(ArrayList<String> bitacoraClientes) {
        this.bitacoraClientes = bitacoraClientes;
    }

    public void obtenerBitacora(){
        ArrayList<String> bitacora= new ArrayList<String>();
        for(ProcesarServidorIndice proceso : listaProcesos ){
            bitacora = proceso.getBitacora();
            bitacoraClientes.addAll(bitacora);
            proceso.limpiarBitacora();
        }        
    }

}
